package br.ufc.spaceinvaders;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;

/**
 * 
 * Classe que representa o Painel que conterá os componentes(imagem de fundo,
 * nave,inimigos)
 * 
 */
public class Fase extends JPanel implements ActionListener {

	private Image fundo;
	private Nave nave;
	private Timer timer;
	private boolean telaInicial;
	private boolean emJogo;
	private boolean ganhouJogo;

	private List<Inimigo> inimigos;
	/**
	 * Coordenadas para inicialização dos inimigos
	 */
	private int[][] coordenadas = { { 2380, 29 }, { 2600, 59 }, { 1380, 89 },
			{ 780, 109 }, { 580, 139 }, { 880, 239 }, { 790, 259 },
			{ 760, 50 }, { 790, 150 }, { 1980, 209 }, { 560, 45 }, { 510, 70 },
			{ 930, 159 }, { 590, 80 }, { 530, 60 }, { 940, 59 }, { 990, 30 },
			{ 920, 200 }, { 900, 259 }, { 660, 50 }, { 540, 90 }, { 810, 220 },
			{ 860, 20 }, { 740, 180 }, { 820, 128 }, { 490, 170 }, { 700, 30 },
			{ 920, 300 }, { 856, 328 }, { 456, 320 } };

	/**
	 * Definição das propriedades do painel, definição de evento de teclado e
	 * inicialização do Timer
	 */
	public Fase() {

		setFocusable(true);
		setDoubleBuffered(true);
		addKeyListener(new TecladoAdapter());
		ImageIcon referencia = new ImageIcon("res/fundo.png");
		fundo = referencia.getImage();
		this.telaInicial = true;

		nave = new Nave();

		emJogo = true;
		ganhouJogo = false;
		inicializaInimigos();

		timer = new Timer(5, this);
		timer.start();
	}

	/**
	 * Método que utiliza as coordenadas para inicializar a List<Inimigo>
	 */
	public void inicializaInimigos() {
		inimigos = new ArrayList<Inimigo>();

		for (int i = 0; i < coordenadas.length; i++) {

			inimigos.add(new Inimigo(coordenadas[i][0], coordenadas[i][1]));

		}
	}

	/**
	 * Método que coloca os gráficos na tela(imagens,nave,inimigos,misseis)
	 */
	public void paint(Graphics g) {
		Graphics2D graficos = (Graphics2D) g;
		graficos.drawImage(fundo, 0, 0, null);
		graficos.drawImage(nave.getImagem(), nave.getX(), nave.getY(), this);
		if (!telaInicial) {
			if (emJogo) {
				List<Missel> misseis = nave.getMisseis();
				for (int i = 0; i < misseis.size(); i++) {
					Missel missel = misseis.get(i);
					graficos.drawImage(missel.getImagem(), missel.getX(),
							missel.getY(), this);
				}

				for (int i = 0; i < inimigos.size(); i++) {
					Inimigo inimigo = inimigos.get(i);
					graficos.drawImage(inimigo.getImagem(), inimigo.getX(),
							inimigo.getY(), this);
				}
			} else if (ganhouJogo) {
				ImageIcon icon = new ImageIcon("res/p1.png");
				graficos.drawImage(icon.getImage(), 0, 0, null);
			} else {
				ImageIcon icon = new ImageIcon("res/game_over.jpg");
				graficos.drawImage(icon.getImage(), 0, 0, null);
			}
		} else {
			ImageIcon icon = new ImageIcon("res/space-invaders.png");
			graficos.drawImage(icon.getImage(), 0, 0, null);
		}

		g.dispose();
	}

	/**
	 * Método de listener chamado pelo Timer, verifica se algum inimigo está
	 * fora do jogo e se o jogo acabou
	 */
	@Override
	public void actionPerformed(ActionEvent arg0) {
		if (inimigos.size() == 0) {
			emJogo = false;
			ganhouJogo = true;
		}
		for (int i = 0; i < inimigos.size(); i++) {
			Inimigo in = inimigos.get(i);
			if (in.isVisivel()) {
				in.mexer();
			} else {
				inimigos.remove(i);
			}
		}
		nave.mexer();
		for (Missel missel : nave.getMisseis()) {
			missel.mexer();
		}
		checarColisoes();
		repaint();

	}

	/**
	 * Método que checa as colisões entre os componentes nave,inimigos e misseis
	 */
	public void checarColisoes() {
		Rectangle formaNave = nave.getBounds();
		Rectangle formaInimigo;
		Rectangle formaMissel;

		for (int i = 0; i < inimigos.size(); i++) {
			Inimigo tempInimigo = inimigos.get(i);
			formaInimigo = tempInimigo.getBounds();

			if (formaNave.intersects(formaInimigo)) {
				nave.setVisivel(false);
				tempInimigo.setVisivel(false);

				emJogo = false;
			}
		}

		List<Missel> misseis = nave.getMisseis();
		for (int i = 0; i < misseis.size(); i++) {

			Missel tempMissel = misseis.get(i);
			formaMissel = tempMissel.getBounds();

			for (int j = 0; j < inimigos.size(); j++) {

				Inimigo tempInimigo = inimigos.get(j);
				formaInimigo = tempInimigo.getBounds();

				if (formaMissel.intersects(formaInimigo)) {
					tempInimigo.setVisivel(false);
					tempMissel.setVisivel(false);

				}

			}
		}
	}

	/**
	 * 
	 * Classe para evento do teclado
	 */
	private class TecladoAdapter extends KeyAdapter {

		/**
		 * Evento de precionar tecla. Sua funcionalidade é verificar a tecla
		 * pressionada e executar ações que inicializam o jogo, reiciniam o jogo
		 * ou apenas chama o método que trata evento de teclado da classe nave
		 */
		@Override
		public void keyPressed(KeyEvent e) {
			if (e.getKeyCode() == KeyEvent.VK_ENTER && telaInicial) {
				telaInicial = false;
				nave = new Nave();
				// inicializaInimigos
				// inicializa emJogo
			} else if (e.getKeyCode() == KeyEvent.VK_ENTER && !emJogo) {
				Fase.this.nave = new Nave();
				inicializaInimigos();
				emJogo = true;
				Fase.this.ganhouJogo = false;
			}
			nave.keyPressed(e);
		}

		/**
		 * Apenas chama o método que trata evento de teclado da classe nave
		 */
		@Override
		public void keyReleased(KeyEvent e){
			nave.keyReleased(e);
		}

	}
}
